/* Team 5
 * James McQueen
 * Corwyn Simpson
 * May 1 ish, 2012
 */
package spider.stores;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import spider.models.Page;
/**
 * A buffer for Pages fetched by a Retriever to be parsed by a Parser.
 * @author James McQueen
 * @author Corwyn Simpson
 */
public class PageBuffer 
{
    /**
     * A BlockingQueue that stores the Pages. This is thread-safe, so no 
     * synchronization is needed when changing this.
     */
    private BlockingQueue<Page> my_page_queue;
    
    /**
     * Creates a new PageBuffer with some_max_capacity.
     * @param some_max_capacity The number of pages that this buffer is allowed
     * to hold. 
     */
    public PageBuffer(final int some_max_capacity)
    {
        my_page_queue = new LinkedBlockingQueue<Page>(some_max_capacity);
    }
    
    /**
     * Adds the_page to the PageBuffer, blocking the thread if it is full.
     * @param the_page The Page to add to the queue. If adding this to the queue
     * would exceed the capacity, it will make the thread wait until a Page is
     * removed by another thread.
     * @throws InterruptedException if the queue was full when this was called 
     * and the thread was interrupted while it was waiting.
     */
    public void addPage(final Page the_page) throws InterruptedException
    {
        my_page_queue.put(the_page);
    }
    
    /**
     * Removes a Page from the PageBuffer, blocking if it is empty.
     * @return The Page at the front of the queue. If the queue is empty, it 
     * will make the thread wait until a Page is added by another thread.
     * @throws InterruptedException if the queue was empty when this was called
     * and the thread was interrupted while it was waiting.
     */
    public Page removePage() throws InterruptedException
    {
        return my_page_queue.take();
    }
    
    /**
     * Returns true if the buffer is empty.
     */
    public boolean isEmpty()
    {
        return my_page_queue.isEmpty();
    }
    
    /**
     * Returns the number of Pages that can be added before adding another page
     * will block that thread.
     */
    public int remainingCapacity()
    {
        return my_page_queue.remainingCapacity();
    }
    
    @Override
    public String toString()
    {
        StringBuilder page_text = new StringBuilder();
        page_text.append("PageBuffer Contents");
        page_text.append("\n");
        for(Page page : my_page_queue)
        {
            page_text.append(page.toString());
            page_text.append("\n");
        }
        return page_text.toString();
    }

    /**
     * Clears the PageBuffer.
     */
    public void clear()
    {
        my_page_queue.clear();
    }
}
